package com.harvestdiary.ui.controller.homepage;

import cn.hutool.core.date.ChineseDate;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.chinese.SolarTerms;
import cn.hutool.json.JSONUtil;
import com.harvestdiary.other.tools.HttpUtil;
import com.harvestdiary.other.tools.OperationalDocument;
import com.harvestdiary.other.tools.SettingFontIcon;
import com.harvestdiary.pojo.Diary;
import com.harvestdiary.pojo.Lattice;
import com.harvestdiary.pojo.UserStatus;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXCheckBox;
import de.felixroske.jfxsupport.FXMLController;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import lombok.extern.slf4j.Slf4j;
import org.kordamp.ikonli.antdesignicons.AntDesignIconsOutlined;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;


@Slf4j
@FXMLController
public class CalendarUIController {
    @FXML
    private Label month;
    @FXML
    private JFXButton backToToday;
    @FXML
    private JFXButton next;
    @FXML
    private JFXButton prev;
    @FXML
    private GridPane calendar;
    @FXML
    private Label date;
    @FXML
    private Label dateOfChinese;
    @FXML
    private Text festivals;
    @FXML
    private JFXCheckBox diary;
    @FXML
    private JFXCheckBox sDiary;
    UserStatus userStatus;

    List<Lattice> list = new ArrayList<>();
    LocalDate checkDate = LocalDate.now();

    @FXML
    public void initialize() {
        //设置按钮的图标
        setIcon();
        setCalendar(checkDate);
    }

    @FXML
    void backToToday(MouseEvent event) {
        checkDate = LocalDate.now();
        setCalendar(checkDate);
    }
    @FXML
    void prev(MouseEvent event) {
        checkDate = checkDate.withDayOfMonth(1).minusMonths(1);
        setCalendar(checkDate);
    }
    @FXML
    void next(MouseEvent event) {
        checkDate = checkDate.withDayOfMonth(1).plusMonths(1);
        setCalendar(checkDate);
    }

    private void setCalendar(LocalDate today) {
        clearCalender();

        int count = 0;
        for (int row = 1; row < 6; row++) {
            for (int col = 0; col < 7; col++) {
                list.add(new Lattice());

                calendar.add(list.get(count).getStackPane(), col, row);
                count++;
            }
        }
        //给格子添加点击事件
        setCalendarEvent();
        //设置每个格子样式
        setLattices(today);
    }

    private void setCalendarEvent() {
        for (Lattice lattice : list) {
            lattice.getJfxButton().setOnAction(event -> {
                latticeToRed(lattice);
                if (!checkMonth(lattice)) {
                    clearCalender();
                    setCalendar(checkDate);
                } else setRightSide(lattice.getLocalDate());
            });
        }
    }

    private Boolean checkMonth(Lattice lattice) {
        LocalDate day = lattice.getLocalDate();
        if (day.getMonthValue() == checkDate.getMonthValue()) {
            checkDate = day;
            return true;
        }
        checkDate = day;
        return false;
    }

    private void clearCalender() {
        for (Lattice lattice : list) {
            calendar.getChildren().remove(lattice.getStackPane());
        }
        list.clear();
    }

    private void setLattices(LocalDate today) {
        // 获取当前月份，转成中文
        month.setText(getChineseYearAndMonth(today));

        // 获取这个月的第一天日期
        LocalDate firstDayOfMonth = today.withDayOfMonth(1);

        // 获取这个月的最后一天日期
        LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());

        int count = 1;
        //星期一 ~星期天， 是 0~6；
        int firstDayOfWeekValue = firstDayOfMonth.getDayOfWeek().getValue() - 1;
        int lastLattice = 35 - firstDayOfWeekValue;


        while (lastLattice >= count) {
            //设置这个月1日开头的农历和1日的格子
            ChineseDate chineseDate = new ChineseDate(firstDayOfMonth);
            Lattice lattice = list.get(firstDayOfWeekValue);

            lattice.getDate().setText(firstDayOfMonth.getDayOfMonth() + "");

            //如果有24节气就显示24节气
            if (!SolarTerms.getTerm(chineseDate).isEmpty())
                lattice.getChineseDate().setText(SolarTerms.getTerm(chineseDate));
            else if (!chineseDate.getFestivals().isEmpty())
                lattice.getChineseDate().setText(chineseDate.getFestivals());
            else lattice.getChineseDate().setText(chineseDate.getChineseDay());

            //设置如果不是这个月的，是下个月的话透明度降低
            if (count > lastDayOfMonth.getDayOfMonth()) lattice.getStackPane().setOpacity(0.3);

            lattice.setLocalDate(firstDayOfMonth);

            firstDayOfMonth = firstDayOfMonth.plusDays(1);
            firstDayOfWeekValue++;
            count++;
        }

        // 获取这个月的第一天的日期
        firstDayOfMonth = today.withDayOfMonth(1);
        firstDayOfWeekValue = firstDayOfMonth.getDayOfWeek().getValue() - 1;


        for (int i = firstDayOfWeekValue - 1; i >= 0; i--) {
            firstDayOfMonth = firstDayOfMonth.minusDays(1);

            ChineseDate chineseDate = new ChineseDate(firstDayOfMonth);

            Lattice lattice = list.get(i);
            //上个月的透明度降低
            lattice.getStackPane().setOpacity(0.3);

            lattice.getDate().setText(firstDayOfMonth.getDayOfMonth() + "");

            //如果有24节气就显示24节气
            if (SolarTerms.getTerm(chineseDate).isEmpty())
                lattice.getChineseDate().setText(chineseDate.getChineseDay());
            else lattice.getChineseDate().setText(SolarTerms.getTerm(chineseDate));

            lattice.setLocalDate(firstDayOfMonth);
        }

        setRightSide(today);

    }

    private String getChineseYearAndMonth(LocalDate today) {
        // 创建一个 DateTimeFormatter 对象，指定日期格式和Locale.CHINA
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月", Locale.CHINA);

        // 使用 formatter 对象格式化 LocalDate
        return today.format(formatter);
    }

    private void latticeToRed(Lattice lattice) {
        allLatticeToBlack();
        lattice.getDate().setTextFill(Color.RED);
        lattice.getChineseDate().setTextFill(Color.RED);
    }

    private void allLatticeToBlack() {
        for (Lattice lattice : list) {
            lattice.getDate().setTextFill(Color.BLACK);
            lattice.getChineseDate().setTextFill(Color.BLACK);
        }
    }
    private void setRightSide(LocalDate today) {
        // 获取这个月的第一天的日期
        LocalDate firstDayOfMonth = today.withDayOfMonth(1);
        int firstDayOfWeekValue = (firstDayOfMonth.getDayOfWeek().getValue() - 1) + (today.getDayOfMonth() - 1);

        ChineseDate chineseDate = new ChineseDate(today);

        date.setText(DateUtil.format(today.atStartOfDay(), "MM月dd日"));
        dateOfChinese.setText(chineseDate.toString());


        festivals.setText(chineseDate.getCyclicalYMD() + "\n" + SolarTerms.getTerm(chineseDate) + chineseDate.getFestivals());


        if (firstDayOfWeekValue >= 35) return;

        latticeToRed(list.get(firstDayOfWeekValue));
        Thread thread = new Thread(() -> {
            Platform.runLater(() -> {
                findAllDiary(today);
            });
        });
        thread.start();
    }

    private void findAllDiary(LocalDate today) {
        diary.setSelected(false);
        sDiary.setSelected(false);
        userStatus = JSONUtil.toBean(OperationalDocument.readFile("userStatus.json"), UserStatus.class);

        findDiary(userStatus.getLocalLogin());

        if (!userStatus.getLocalLogin()) findSDiary();


        setCheckBox(today);
    }

    private void findDiary(Boolean localLogin) {
        List<Diary> diaryList = findToDiaryList(localLogin);

        list.stream()
                .filter(localDate -> diaryList.stream()
                        .anyMatch(time -> (time.getTime()
                                .equals(localDate.getLocalDate().toString()))))
                .forEach(matchedDiary -> {
                    matchedDiary.getDiary().setOpacity(1);
                });


    }

    private List<Diary> findToDiaryList(Boolean localLogin) {
        List<String> list = OperationalDocument.readDiaries(userStatus.getUserId(), localLogin);
        List<Diary> diaryList = new ArrayList<>();

        for (String s : list) {
            Diary d = JSONUtil.toBean(OperationalDocument.readDiary(s), Diary.class);
            diaryList.add(d);
        }

        return diaryList;
    }

    private void findSDiary() {
        String json = HttpUtil.httpResponse("/diary/getDiary", userStatus.getUserId());

        String data = JSONUtil.parseObj(json).getStr("data");
        List<Diary> diaryList = JSONUtil.toList(JSONUtil.parseArray(data), Diary.class);


        list.stream()
                .filter(localDate -> diaryList.stream()
                        .anyMatch(time -> (time.getTime()
                                .equals(localDate.getLocalDate().toString()))))
                .forEach(matchedDiary -> {
                    matchedDiary.getSDiary().setOpacity(1);
                });

    }

    private void setCheckBox(LocalDate today){
        for (Lattice lattice : list) {
            if (lattice.getLocalDate().equals(today)){
                if (lattice.getDiary().getOpacity() == 1) diary.setSelected(true);

                if (lattice.getSDiary().getOpacity() == 1) sDiary.setSelected(true);

                break;
            }
        }
    }

    private void setIcon(){
        backToToday.setGraphic(SettingFontIcon.setSizeAndColor(AntDesignIconsOutlined.RELOAD, 14, Color.web("#617172")));
        prev.setGraphic(SettingFontIcon.setSizeAndColor(AntDesignIconsOutlined.CARET_LEFT, 18, Color.web("#617172")));
        next.setGraphic(SettingFontIcon.setSizeAndColor(AntDesignIconsOutlined.CARET_RIGHT, 18, Color.web("#617172")));
    }
}
